home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
-
- #define TRUE 1
- #define FALSE 0
- #define ERR (-1)
-
- static unsigned long midi_clock = 0;
-
- static unsigned long getdword(char *p)
- {
- unsigned long l;
-
- l = (unsigned char)(*(p++)); l <<= 8;
- l |= (unsigned char)(*(p++)); l <<= 8;
- l |= (unsigned char)(*(p++)); l <<= 8;
- l |= (unsigned char)(*(p++));
- return l;
- }
- static unsigned long get3byte(char *p)
- {
- unsigned long l;
-
- l = (unsigned char)(*(p++)); l <<= 8;
- l |= (unsigned char)(*(p++)); l <<= 8;
- l |= (unsigned char)(*(p++));
- return l;
- }
- static int getword(char *p)
- {
- int i;
-
- i = (unsigned char)(*(p++)); i <<= 8;
- i |= (unsigned char)(*(p++));
- return i;
- }
- static int getdelta(char *p, unsigned long *delta)
- {
- int n = 0;
-
- *delta = 0;
- while ( (p[n] & 0x80) != 0 ) {
- *delta |= (p[n++] & 0x7F);
- *delta = (*delta << 7);
- }
- *delta |= p[n++];
- return n;
- }
- static void MIDI_clock_count()
- {
- midi_clock++;
- }
- int PLAY_midi(char *file)
- {
- int n, i;
- int sw,x,y;
- FILE *fp;
- unsigned long file_size;
- unsigned long size;
- unsigned long delta;
- unsigned long clk;
- char *top, *ptr, *btm;
- int format, ntrks, division;
- int port, track, tempo, st;
- struct {
- char *ptr;
- char *btm;
- char cmd;
- unsigned long clk;
- } trtab[32];
- char tmp[4];
- char note[16][128];
- int dsp = 0;
-
- DSP_mos(2);
- if( (fp = fopen(file, "rb")) == NULL ) {
- DSP_mos(0);
- kakunin("MIDIファイルのオープンに失敗しました");
- return ERR;
- }
-
- fseek(fp, 0L, SEEK_END);
- file_size = ftell(fp);
- rewind(fp);
-
- if( (top = (char *)malloc((int)file_size)) == NULL ) {
- DSP_mos(0);
- fclose(fp);
- kakunin("メモリが足りませんでした");
- return ERR;
- }
-
- if ( fread(top, (int)file_size, 1, fp) != 1 ) {
- DSP_mos(0);
- kakunin("MIDIファイルの読み込みに失敗しました");
- return ERR;
- }
- fclose(fp);
- DSP_mos(0);
-
- ptr = top;
- btm = top + file_size;
-
- if ( strncmp(ptr, "MThd", 4) != 0 &&
- file_size > (128 + 8) &&
- strncmp(ptr + 128, "MThd", 4) == 0 ) {
- ptr += 128;
- }
-
- while ( strncmp(ptr, "MThd", 4) != 0 ) {
- size = getdword(ptr + 4);
- if ( (ptr += (8 + size)) >= btm )
- goto ERROR;
- }
-
- size = getdword(ptr + 4);
- ptr += 8;
- format = getword(ptr + 0);
- ntrks = getword(ptr + 2);
- division = getword(ptr + 4);
- ptr += size;
-
- if ( ntrks <= 0 || division <= 0 )
- goto ERROR;
-
- for ( track = 0 ; track < 32 && track < ntrks && ptr < btm ; track++ ) {
- while ( strncmp(ptr, "MTrk", 4) != 0 ) {
- size = getdword(ptr + 4);
- if ( (ptr += (8 + size)) >= btm )
- goto ERROR;
- }
-
- size = getdword(ptr + 4);
- ptr += 8;
-
- trtab[track].btm = ptr + size;
- trtab[track].ptr = ptr + getdelta(ptr, &delta);
- trtab[track].clk = delta;
- trtab[track].cmd = 0x00;
-
- ptr += size;
- }
- ntrks = track;
-
- port = 0;
- tempo = 120;
- midi_clock = 0;
- st = FALSE;
- memset(note, 0, 16 * 128);
-
- EUP_open();
-
- SND_int_timer_a_set(MIDI_clock_count);
- SND_fm_timer_a_set(0, 1024 - 17361 / tempo);
- SND_fm_timer_a_start();
-
- while ( st == FALSE ) {
- st = TRUE;
- clk = midi_clock * division / 192;
- for ( track = 0 ; track < ntrks ; track++ ) {
- ptr = trtab[track].ptr;
- while ( ptr < trtab[track].btm &&
- trtab[track].clk <= clk ) {
-
- if ( (*ptr & 0x80) == 0 )
- *(--ptr) = trtab[track].cmd;
-
- switch(*(ptr) & 0xF0) {
- case 0x90:
- trtab[track].cmd = *ptr;
- ptr[1] &= 0x7F;
- ptr[2] &= 0x7F;
- if ( ptr[2] == 0 )
- ptr[0] &= 0x8F;
- else
- EUP_note_on(ptr[1] / 4, ptr[2] & 127);
- SND_midi_write(port, ptr, 3);
- note[ptr[0] & 0x0F][ptr[1]] = ptr[2];
- ptr += 3;
- break;
-
- case 0x80:
- trtab[track].cmd = *ptr;
- ptr[1] &= 0x7F;
- ptr[2] &= 0x7F;
- SND_midi_write(port, ptr, 3);
- note[ptr[0] & 0x0F][ptr[1]] = ptr[2];
- ptr += 3;
- break;
-
- case 0xA0: case 0xB0: case 0xE0:
- trtab[track].cmd = *ptr;
- SND_midi_write(port, ptr, 3);
- ptr += 3;
- break;
-
- case 0xC0: case 0xD0:
- trtab[track].cmd = *ptr;
- SND_midi_write(port, ptr, 2);
- ptr += 2;
- break;
-
- case 0xF0:
- trtab[track].cmd = 0x00;
- switch(*(ptr) & 0xFF) {
- case 0xF0:
- ptr += 1;
- SND_midi_write(port, "\xFF", 1);
- ptr += getdelta(ptr, &delta);
- SND_midi_write(port, ptr, delta);
- ptr += delta;
- break;
-
- case 0xF7:
- ptr += 1;
- ptr += getdelta(ptr, &delta);
- SND_midi_write(port, ptr, delta);
- ptr += delta;
- break;
-
- case 0xF2:
- ptr += 2;
- break;
-
- case 0xF3:
- ptr += 3;
- break;
-
- case 0xF1:
- case 0xF4:
- case 0xF5:
- case 0xF6:
- case 0xF8:
- case 0xFA:
- case 0xFB:
- case 0xFC:
- case 0xFD:
- case 0xFE:
- ptr += 1;
- break;
-
- case 0xFF:
- switch(*(ptr + 1) & 0xFF) {
- case 0x2F: /* end of */
- ptr = trtab[track].btm;
- break;
-
- case 0x51: /* tempo */
- delta = get3byte(ptr + 3);
- if ( delta > 0 ) {
- if ( (tempo = 60000000L / delta) < 30 )
- tempo = 30;
- else if ( tempo > 280 )
- tempo = 280;
- }
- SND_fm_timer_a_set(0xFF, 1024 - 17361 / tempo);
- break;
- }
- ptr += 2;
- ptr += getdelta(ptr, &delta);
- ptr += delta;
- break;
- }
- break;
-
- default:
- ptr++;
- break;
- }
- ptr += getdelta(ptr, &delta);
- trtab[track].clk += delta;
- }
- if ( (trtab[track].ptr = ptr) < trtab[track].btm )
- st = FALSE;
- }
- EUP_chk(NULL);
- MOS_rdpos(&sw, &x, &y);
- if ( sw != 0 )
- break;
- }
-
- ENDOF:
-
- SND_fm_timer_a_set(0, 1024 - 17361 / tempo);
- for ( i = 0 ; i < 16 ; i++ ) {
- for ( n = 0 ; n < 128 ; n++ ) {
- if ( note[i][n] > 0 ) {
- tmp[0] = 0x80 | i;
- tmp[1] = n;
- tmp[2] = 0;
- SND_midi_write(port, tmp, 3);
- }
- }
- }
-
- EUP_close();
- free(top);
- return FALSE;
-
- ERROR:
- free(top);
- kakunin("対応していないMIDIファイルです");
- return ERR;
- }